package com.operate.api.app.user.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.db.nosql.redis.RedisDS;
import com.operate.api.app.user.dao.AppUserDao;
import com.operate.api.app.user.domain.po.AppUserPO;
import com.operate.api.app.user.domain.vo.*;
import com.operate.api.app.user.service.IAppUserService;
import com.operate.api.base.Constants;
import com.operate.api.base.IDEntity;
import com.operate.api.base.RedisUtils;
import com.operate.api.base.Type;
import com.operate.exception.BusinessException;
import com.operate.util.HuaWeiSMSUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.TimeUnit;


@Service
@Transactional
@Slf4j
public class AppUserServiceImpl implements IAppUserService {

    @Autowired
    private AppUserDao dao;

    // 序列化对象redis处理方法
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public List<AppUserVO> getList(AppUserSearchVO searchVO) {
        return dao.getList(searchVO);
    }

    @Override
    public AppUserLoginResVO login(AppUserLoginReqVO vo) {
        Example sysExample = new Example(AppUserPO.class);
        sysExample.and().andEqualTo("userPhone",vo.getUserPhone())
                .andEqualTo("delFlag", false);
        AppUserPO loginUser=dao.selectOneByExample(sysExample);
        if(loginUser==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"登陆用户信息不存在！");
        }
        if(StringUtils.isBlank(loginUser.getUserPassword())||!loginUser.getUserPassword().equals(vo.getPassword())){
            throw new BusinessException(Type.FAIL.getCode(),"账号密码错误！");
        }
        return getLoginResVO(loginUser);

    }

    @Override
    public AppUserLoginResVO loginCode(AppUserPhoneCodeVO vo) {
         checkCodes(vo);
        Example sysExample = new Example(AppUserPO.class);
        sysExample.and().andEqualTo("userPhone",vo.getUserPhone())
                .andEqualTo("delFlag", false);
        AppUserPO loginUser=dao.selectOneByExample(sysExample);
        if(loginUser==null){
            //如果没有就注册一个用户
            loginUser=new AppUserPO();
            loginUser.setUserPhone(vo.getUserPhone());
            loginUser.setRechargeMoney(BigDecimal.ZERO);
            loginUser.setUserBalance(BigInteger.ZERO);
            loginUser.setUserName("剧艺用户"+RandomUtil.randomString(5));
            loginUser.preInsert();
            int i =  dao.insertSelective(loginUser);
            if (i == Constants.SQL_RETURN_SUCCESS) {
                throw new BusinessException(Type.FAIL);
            }
        }
        return getLoginResVO(loginUser);
    }

    private AppUserLoginResVO getLoginResVO(AppUserPO loginUser) {
        StpUtil.login(loginUser.getId());
        AppUserLoginResVO userLoginResVO = new AppUserLoginResVO();
        userLoginResVO.setId(loginUser.getId());
        userLoginResVO.setToken(StpUtil.getTokenValue());
        userLoginResVO.setUserName(loginUser.getUserName());
        userLoginResVO.setUserPhone(loginUser.getUserPhone());
        return userLoginResVO;
    }

    @Override
    public void checkCode(AppUserPhoneCodeVO vo) {
         checkCodes(vo);
    }

    private void checkCodes(AppUserPhoneCodeVO vo) {
        String code = redisUtils.get("code_"+vo.getUserPhone());
        log.info("验证验证码是否有效"+vo.getUserPhone()+"_"+code);
        if (StringUtils.isBlank(code)) {
            throw new BusinessException(Type.FAIL.getCode(), "短信验证码已失效！");
        }
        if (!code.equals(vo.getCode())) {
            throw new BusinessException(Type.FAIL.getCode(), "短信验证码不正确！");
        }
        redisUtils.deleteString("code_"+vo.getUserPhone());
    }

    @Override
    public void updatePassword(AppUserUpdatePasswordVO vo) {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        if(!vo.getOldPassword().equals(appUserPO.getUserPassword())){
            throw new BusinessException(Type.FAIL.getCode(), "旧密码不正确！");
        }
        if(!vo.getConfirmPassword().equals(vo.getResetPassword())){
            throw new BusinessException(Type.FAIL.getCode(), "新密码和确认密码不一样！");
        }
        appUserPO.setUserPassword(vo.getResetPassword());
        appUserPO.preUpdate();
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }
    }

    @Override
    public void resetPassword(AppUserPasswordVO vo) {
        Example sysExample = new Example(AppUserPO.class);
        sysExample.and().andEqualTo("userPhone",vo.getUserPhone())
                .andEqualTo("delFlag", false);
        AppUserPO loginUser=dao.selectOneByExample(sysExample);
        if(loginUser==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"用户信息不存在！");
        }
        loginUser.setUserPassword(vo.getResetPassword());
        loginUser.preUpdate();
        int i = dao.updateByPrimaryKeySelective(loginUser);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }

    }

    public static void main(String[] args) {
        System.out.println(DateUnit.SECOND.getMillis());
    }

    public static Cache<String,String> fifoCache = CacheUtil.newFIFOCache(10000);
    @Override
    public void sendCode(AppCodeVO vo) {
        String code=String.valueOf(RandomUtil.randomInt(100000,999999));
        String oldCode=fifoCache.get(vo.getUserPhone()+"_check");
        if(StringUtils.isNotBlank(oldCode)){
            throw new BusinessException(Type.FAIL.getCode(),"请一分钟后再试");
        }
        fifoCache.put(vo.getUserPhone()+"_check",code, DateUnit.SECOND.getMillis() *60 );
        redisUtils.set("code_"+vo.getUserPhone(), code,2, TimeUnit.HOURS);
        log.info(vo.getUserPhone()+":::::::::::::"+redisUtils.get("code_"+vo.getUserPhone()));
        try {
            if(!HuaWeiSMSUtil.sendSms(code,vo.getUserPhone(),HuaWeiSMSUtil.sender,HuaWeiSMSUtil.templateId)){
                throw new BusinessException(Type.FAIL);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException(Type.FAIL);
        }
    }

    @Override
    public void updatePhone(AppUserPhoneCodeVO vo) {
        checkCodes(vo);
        Example example=new Example(AppUserPO.class);
        example.and().andEqualTo("userPhone",vo.getUserPhone());
        Integer count=dao.selectCountByExample(example);
        if(count>0){
            throw new BusinessException(Type.FAIL.getCode(),"手机号已经绑定用户！");
        }
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        appUserPO.setUserPhone(vo.getUserPhone());
        appUserPO.preUpdate();
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }
    }

    @Override
    public AppUserVO getOne() {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        AppUserVO vo=new AppUserVO();
        BeanUtils.copyProperties(appUserPO,vo);
        vo.setIsPassword(1);
        if(StringUtils.isBlank(appUserPO.getUserPassword())){
            vo.setIsPassword(2);
        }
        vo.setYoungCompanyId("1721071054825088888");
        return vo;
    }

    @Override
    public void loginOut() {
        StpUtil.logout();
    }

    @Override
    public void logOff() {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        if(appUserPO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"登陆用户信息不存在！");
        }
        appUserPO.setUserPhone(appUserPO.getUserPhone()+"_"+RandomUtil.randomString(3));
        appUserPO.setUserPassword("");
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }
        StpUtil.logout();
    }

    @Override
    public void close_young(IDEntity idEntity) {
        if(StringUtils.isBlank(idEntity.getId())){
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL);
        }
        AppUserPO appUserPO=dao.selectByPrimaryKey(idEntity.getId());
        if(appUserPO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR);
        }
        if(appUserPO.getIsYoung()==2){
            throw new BusinessException(Type.EXIST_ERROR.getCode(),"当前用户已经关闭青少年模式，请勿重复操作");
        }
        appUserPO.setIsYoung(2);
        appUserPO.preUpdate();
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }
    }

    @Override
    public void open_young_password(AppUserYoungPasswordVO vo) {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        if(appUserPO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"登陆用户信息不存在！");
        }
        if(appUserPO.getIsYoung()==1){
            throw new BusinessException(Type.EXIST_ERROR.getCode(),"当前用户已经开启了青少年模式，请勿重复操作");
        }
        appUserPO.setIsYoung(1);
        appUserPO.setYoungPassword(vo.getPassword());
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }
    }

    @Override
    public void close_young_password(AppUserYoungPasswordVO vo) {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        if(appUserPO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"登陆用户信息不存在！");
        }
        if(appUserPO.getIsYoung()==2){
            throw new BusinessException(Type.EXIST_ERROR.getCode(),"当前用户已经关闭青少年模式，请勿重复操作");
        }
        if(!vo.getPassword().equals(appUserPO.getYoungPassword())){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"关闭失败，密码错误！");
        }
        appUserPO.setIsYoung(2);
        int i = dao.updateByPrimaryKeySelective(appUserPO);
        if (i == Constants.SQL_RETURN_SUCCESS) {
            throw new BusinessException(Type.FAIL);
        }

    }

    @Override
    public void check_young_password(AppUserYoungPasswordVO vo) {
        AppUserPO appUserPO=dao.selectByPrimaryKey(StpUtil.getLoginId());
        if(appUserPO==null){
            throw new BusinessException(Type.NOT_FOUND_ERROR.getCode(),"登陆用户信息不存在！");
        }
        if(appUserPO.getIsYoung()==2){
            throw new BusinessException(Type.EXIST_ERROR.getCode(),"当前用户已经关闭青少年模式");
        }
        if(!vo.getPassword().equals(appUserPO.getYoungPassword())){
            throw new BusinessException(Type.PARAM_VALIDATE_FAIL.getCode(),"验证失败，密码不匹配！");
        }
    }
}